package com.sh.cloudrender.application.service;

import com.sh.cloudrender.application.dto.access.AccessDTO;
import com.sh.cloudrender.infrastructure.repository.AccessRepo;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.nio.charset.StandardCharsets;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;
import java.util.*;

@Slf4j
@Service
public class AccessServiceImpl implements AccessService {
    private static final int ACCESS_KEY_LENGTH = 20;  // 可以根据需要调整长度
    private static final int ACCESS_KEY_SECRET_LENGTH = 40;  // 可以根据需要调整长度
    private static SecureRandom random = new SecureRandom();

    @Autowired
    private AccessRepo accessRepo;

    @Override
    public AccessDTO create(String userId) {
        String accessKey = generateFromUserId(userId, ACCESS_KEY_LENGTH);
        String accessSecret = generateFromUserId(userId, ACCESS_KEY_SECRET_LENGTH);
        AccessDTO accessDTO = new AccessDTO();
        accessDTO.setAccessKey(accessKey);
        accessDTO.setAccessSecret(accessSecret);
        accessDTO.setCreateTime(new Date());
        accessDTO.setDisable(0);
        if (accessRepo.save(userId, accessDTO)) {
            return accessDTO;
        }

        return null;
    }

    @Override
    public boolean disable(String userId, String accessKey) {
        return accessRepo.disableByKey(userId, accessKey);
    }

    @Override
    public boolean updateUsedTime(String userId, String accessKey) {
        return accessRepo.updateLastUsedTime(userId, accessKey);
    }

    @Override
    public AccessDTO findBy(String userId, String accessKey) {
        return accessRepo.findByKey(userId, accessKey);
    }

    @Override
    public List<AccessDTO> listBy(String userId) {
        return accessRepo.findByUserId(userId);
    }

    @Override
    public boolean validate(String userId, String accessKey, String accessSecret) {
        AccessDTO dto = accessRepo.findByKey(userId, accessKey);
        if (dto == null){
            return false;
        }

        String storedAccessKey = dto.getAccessKey();
        String storedAccessKeySecret = dto.getAccessSecret();
        return storedAccessKey != null && storedAccessKey.equals(accessKey) &&
                storedAccessKeySecret != null && storedAccessKeySecret.equals(accessSecret);
    }

    @Override
    public boolean addressValidate(String accessKeySHA256, String engineId) {
        System.out.println("This position!");
        List<AccessDTO> accessDTO = accessRepo.getAccessKeyByEngineId(engineId);
        if(accessDTO == null){
            return false;
        }

        for(AccessDTO tempAccessDTO : accessDTO) {
            String tempAccessKey = tempAccessDTO.getAccessKey();
            byte[] hash = hash(tempAccessKey);

            StringBuilder hexString = new StringBuilder();
            for (byte b : hash) {
                String hex = Integer.toHexString(0xff & b);
                if (hex.length() == 1) {
                    hexString.append('0'); // 补齐一位
                }
                hexString.append(hex);
            }

            if(accessKeySHA256.equals(hexString.toString())) {
                return true;
            }
        }
        return false;
    }

    private String generateFromUserId(String userId, int length) {
        String base = userId + System.currentTimeMillis() + random.nextInt();
        byte[] hash = hash(base);
        return encodeToBase64(hash).substring(0, length);
    }

    private byte[] hash(String input) {
        try {
            MessageDigest digest = MessageDigest.getInstance("SHA-256");
            return digest.digest(input.getBytes(StandardCharsets.UTF_8));
        } catch (NoSuchAlgorithmException e) {
            throw new RuntimeException("SHA-256 algorithm not found", e);
        }
    }

    private String encodeToBase64(byte[] hash) {
        return Base64.getUrlEncoder().withoutPadding().encodeToString(hash);
    }
}
